import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
import io from "socket.io-client/dist/socket.io.js";
// const io = {}
// const { io } = require("socket.io-client");
@ccclass('Socket')
export class Socket extends Component {
    ip = "";
    sio = null;
    isPinging = false;
    fnDisconnect = null;
    delayMS = 0;
    lastRecieveTime = 0;
    lastSendTime = 0;
    handlers = {} as any;
    addHandler(event: string, fn: any) {
        if (this.handlers[event]) {
            return;
        }
        let handler = function (data) {
            if (event != "disconnect" && typeof data === "string") {
                data = JSON.parse(data);
            }
            fn(data);
        }
        this.handlers[event] = handler;
        if (this.sio) {
            this.sio.on(event, handler);
        }
    }
    connect(fn: any) {
        let opts = {
            reconnection: false,
            "force new connection": true,
            "transports": ["websocket", "polling"]
        }
        this.sio = io.connect(this.ip, opts);
        this.sio.on("reconnect", e => {
            console.log("reconnect => ", e)
        })
        this.sio.on("connect", data => {
            this.sio.connectd = true;
            fn(data);
        })
        this.sio.on("disconnect", e => {
            this.sio.connectd = false;
            this.close();
        })

        this.sio.on("connect_failed", e => {
            console.log("connect fail => ", e)
        })
        for (let k in this.handlers) {
            let v = this.handlers[k];
            if (typeof v === "function") {
                if (k == "disconnect") {
                    this.fnDisconnect = v;
                } else {
                    this.sio.on(k, v);
                }
            }
        }

        this.startHearbeat();
    }
    startHearbeat() {
        this.sio.on("game_pong", e => {
            this.lastRecieveTime = Date.now();
            this.delayMS = this.lastRecieveTime - this.lastSendTime;
        })
        this.lastRecieveTime = Date.now();
        if (!this.isPinging) {
            this.isPinging = true;
            cc.game.on(cc.game.EVENT_HIDE, () => {
                this.ping();
            })
            setInterval(() => {
                if (this.sio) {
                    if (Date.now() - this.lastRecieveTime > 10 * 1000) {
                        this.close();
                    }
                }
            }, 500)
        }
    }
    send(event, data = '') {
        if (this.sio.connectd) {
            if (data != null && typeof data === "object") {
                data = JSON.stringify(data);
            }
            if (data == null) {
                data = ''
            }
            this.sio.emit(event, data);
        }
    }
    ping() {
        if (this.sio) {
            this.lastSendTime = Date.now();
            this.send('game_ping');
        }
    }
    close() {
        this.delayMS = null;
        if (this.sio && this.sio.connectd) {
            this.sio.connectd = false;
            this.sio.disconnect();
        }
        this.sio = null;
        if (this.fnDisconnect) {
            this.fnDisconnect();
            this.fnDisconnect = null;
        }
    }
    start() {

    }

    update(deltaTime: number) {

    }

}

